/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package progin;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.logging.*;

import org.json.*;

/**
 *
 * @author Jiwandono
 */
public class chatEngine extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        try {
            HttpSession session = request.getSession();

            ServletConfig scfg = getServletConfig();
            ServletContext sc = scfg.getServletContext();
            chatData cd = (chatData) sc.getAttribute("ichat.chatdata");
            
            Class.forName("com.mysql.jdbc.Driver");

            dbConfig dbc = new dbConfig();
            Connection con = DriverManager.getConnection(dbc.url, dbc.username, dbc.password);

            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery("SELECT DATE(NOW())"); // testing

            JSONObject responseJSON = new JSONObject();
            
            if(request.getParameter("action").equals("joinroom")) {
                if(cd.isBanned(request.getParameter("roomname"), session.getAttribute("ichat.username").toString())) {
                    responseJSON.put("joinstatus", "false");
                } else {
                    responseJSON.put("joinstatus", "true");

                    cd.joinRoom(request.getParameter("roomname"), session.getAttribute("ichat.username").toString(), session.getAttribute("ichat.usertype").toString());
                    session.setAttribute("ichat.room.lastMsgID." + request.getParameter("roomname"), -1);
                    ArrayList<chatRoom> cr = (ArrayList<chatRoom>) session.getAttribute("ichat.roomdata");
                    cr.add(new chatRoom(0, null, request.getParameter("roomname"), null));

                    // berikan room data
                    JSONObject roomdata = new JSONObject();

                    // room owner
                    roomdata.put("owner", cd.getOwner(request.getParameter("roomname")));

                    // daftar user online
                    JSONArray userlist = new JSONArray();
                    int n = 0;

                    while(n < cd.presence.size()) {
                        if(cd.presence.get(n).room.equals(request.getParameter("roomname")) && !cd.presence.get(n).username.equals(session.getAttribute("ichat.username"))) {
                            JSONObject user = new JSONObject();
                            user.put("username", cd.presence.get(n).username);

                            userlist.put(user);
                        }
                        n++;
                    }

                    roomdata.put("userlist", userlist);

                    responseJSON.put("roomdata", roomdata);
                }

                out.println(responseJSON.toString());
            } else if(request.getParameter("action").equals("senduserchat")) {
                cd.addMessage(request.getParameter("sender"), request.getParameter("receiver"), request.getParameter("room"), request.getParameter("message"));
                JSONObject ack = new JSONObject();
                JSONObject ackcontent = new JSONObject();

                if (request.getParameter("message").startsWith("/")){
                    String teks = request.getParameter("message").substring(1);
                    String temp[] = teks.split(" ");
                    if(temp[0].equals("create")){
                        if (temp.length == 3){
                            //create di bawah prodi/fak apa
                            dbc = new dbConfig();
                            con = DriverManager.getConnection(dbc.url, dbc.username, dbc.password);
                            Statement sts = con.createStatement();
                            ResultSet us = sts.executeQuery("SELECT * FROM `fakultas` where " +
                                    "nama='"+temp[2]+"");

                            us.last();
                            if (us.getRow()>0){
                                cd.addRoom(Integer.parseInt(us.getString("idfakultas")), chatRoom.parentType.fakultas, temp[1], request.getParameter("sender"));
                                ackcontent.put("message", "Room "+temp[1]+" is created.");
                            }else{
                                sts = con.createStatement();
                                us = sts.executeQuery("SELECT * FROM `prodi` where " +
                                    "nama='"+temp[2]+"");
                                us.last();
                                if (us.getRow()>0){
                                    cd.addRoom(Integer.parseInt(us.getString("idprodi")), chatRoom.parentType.prodi, temp[1], request.getParameter("sender"));
                                    ackcontent.put("message", "Room "+temp[1]+" is created.");
                                }else ackcontent.put("message", temp[2]+" isn't found.");
                            }
                        }else if (temp.length==2){
                            //create room default
                        }else {
                            ackcontent.put("message", "Command Unknown. Use format '/create &lt;roomname&gt; [kode_prodi/kode_fakultas]'");
                        }
                    }else
                    if(temp[0].equals("join")){
                        if (temp.length == 2){
                            //join room
                        }else {
                            ackcontent.put("message", "Command Unknown. Use format '/join &lt;roomname&gt;'");
                        }
                    }else
                    if(temp[0].equals("chat")){
                        if (temp.length == 2){
                            //chat ama username
                        }else {
                            ackcontent.put("message", "Command Unknown. Use format '/chat &lt;username&gt;'");
                        }
                    }else
                    if(temp[0].equals("addfriend")){
                        if (temp.length == 2){
                            
                            try {
                                dbc = new dbConfig();
                                con = DriverManager.getConnection(dbc.url, dbc.username, dbc.password);
                                Statement sts = con.createStatement();
                                ResultSet us = sts.executeQuery("SELECT * FROM `friend` where " +
                                        "user1='"+session.getAttribute("ichat.username")+"' AND user2='"+temp[1]+"'");
                                us.last();
                                
                                if (us.getRow()>0){
                                    ackcontent.put("message", "User "+temp[1]+" already in you friend list.");
                                }else{
                                    sts = con.createStatement();
                                    sts.executeUpdate("INSERT INTO `friend` (user1,user2) VALUES " +
                                            "('"+request.getParameter("sender")+"', '"+temp[1]+"')");
                                    ackcontent.put("message", "User "+temp[1]+" now in your friend list.");
                                }
                            } catch (SQLException ex) {
                                Logger.getLogger(chatServlet.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }else {
                            ackcontent.put("message", "Command Unknown. Use format '/addfriend &lt;username&gt;'");
                        }
                    }else
                    if(temp[0].equals("exit")){
                        if (temp.length == 1){
                            //join room
                        }else {
                            ackcontent.put("message", "Command Unknown. Use format '/exit'");
                        }
                    }else
                    if(temp[0].equals("info")){
                        if (temp.length == 1){
                            try {
                                dbc = new dbConfig();
                                con = DriverManager.getConnection(dbc.url, dbc.username, dbc.password);
                                Statement sts = con.createStatement();
                                if(!(request.getParameter("receiver").isEmpty())){
                                    ResultSet us = sts.executeQuery("SELECT * FROM `user` WHERE " +
                                            "username='"+request.getParameter("receiver")+"'");
                                    us.first();
                                    ackcontent.put("message", "User "+request.getParameter("receiver")+" is a "+us.getString("type")+".");
                                }else{
                                    sts = con.createStatement();

                                    int i;
                                    chatRoom auo = null;
                                    for (i=0;i<cd.room.size();i++){
                                        if (cd.room.get(i).name.equals(request.getParameter("room"))){
                                            auo = cd.room.get(i);
                                            break;
                                        }
                                    }

                                    if (auo.parenttype == chatRoom.parentType.fakultas){
                                        ResultSet us = sts.executeQuery("SELECT * FROM `fakultas` WHERE idfakultas ="+auo.parent);
                                        ackcontent.put("message", "Room "+request.getParameter("room")+" is under Fakultas "+us.getString("nama")+".");
                                    }else{
                                        ResultSet us = sts.executeQuery("SELECT idfakultas, idprodi, (fakultas.nama as nama_fakultas), " +
                                            "(prodi.nama as nama_prodi) FROM `prodi`, `fakultas` WHERE idprodi ="+auo.parent+
                                            " ,prodi.idfakultas = fakultas.idfakultas");
                                        ackcontent.put("message", "Room "+request.getParameter("room")+" is under Prodi "+us.getString("nama_prodi")+" in Fakultas "+us.getString("nama_fakultas")+".");
                                    }
                                }
                            } catch (SQLException ex) {
                                Logger.getLogger(chatServlet.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }else if (temp.length == 2){
                            try {
                                dbc = new dbConfig();
                                con = DriverManager.getConnection(dbc.url, dbc.username, dbc.password);
                                Statement sts = con.createStatement();
                                ResultSet us = sts.executeQuery("SELECT * FROM `user` where " +
                                        "username='"+temp[1]+"'");
                                us.last();
                                if (us.getRow()>0){
                                    ackcontent.put("message", "User "+temp[1]+" is a "+us.getString("type")+".");
                                }else{
                                    sts = con.createStatement();

                                    int i;
                                    chatRoom auo = null;
                                    for (i=0;i<cd.room.size();i++){
                                        if (cd.room.get(i).name.equals(temp[1])){
                                            auo = cd.room.get(i);
                                            break;
                                        }
                                    }

                                    if(i!=cd.room.size()){

                                        if (auo.parenttype == chatRoom.parentType.fakultas){
                                            us = sts.executeQuery("SELECT * FROM `fakultas` WHERE idfakultas ="+auo.parent);
                                            ackcontent.put("message", "Room "+temp[1]+" is under Fakultas "+us.getString("nama")+".");
                                        }else{
                                            us = sts.executeQuery("SELECT idfakultas, idprodi, (fakultas.nama as nama_fakultas), " +
                                                "(prodi.nama as nama_prodi) FROM `prodi`, `fakultas` WHERE idprodi ="+auo.parent+
                                                " ,prodi.idfakultas = fakultas.idfakultas");
                                            ackcontent.put("message", "Room "+temp[1]+" is under Prodi "+us.getString("nama_prodi")+" in Fakultas "+us.getString("nama_fakultas")+".");
                                        }
                                    }else ackcontent.put("message", "Info for "+temp[1]+" isn't found.");
                                }
                            } catch (SQLException ex) {
                                Logger.getLogger(chatServlet.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }else{
                            ackcontent.put("message", "Command Unknown. Use format '/info [roomname/username]'");
                        }
                    }else
                    //bagian pemilik room..belum dibedain
                    if(temp[1].equals("kick")){
                        if (temp.length == 3){
                            //kick username
                        }else {
                            //parameter salah
                        }
                    }else
                    if(temp[1].equals("ban")){
                        if (temp.length == 3){
                            //ban username
                        }else {
                            //parameter salah
                        }
                    }else
                    if(temp[1].equals("unban")){
                        if (temp.length == 3){
                            //unban usernames
                        }else {
                            //parameter salah
                        }
                    }else
                    if(temp[1].equals("persist")){
                        if (temp.length == 2){
                            //make room persist
                        }else {
                            //parameter salah
                        }
                    }else
                    if(temp[1].equals("temp")){
                        if (temp.length == 2){
                            //make room temporary
                        }else {
                            //parameter salah
                        }
                    }else
                    if(temp[1].equals("setowner")){
                        if (temp.length == 3){
                            //setowner username
                        }else {
                            //parameter salah
                        }
                    }else{
                        //perintah salah
                        ackcontent.put("message", "Use format '/&lt;command&gt; [parameter]'");
                    }
                }else ackcontent.put("message", request.getParameter("message"));

                ackcontent.put("sender", request.getParameter("sender"));
                ackcontent.put("receiver", request.getParameter("receiver"));
                ackcontent.put("room", request.getParameter("room"));
                //ackcontent.put("message", request.getParameter("message"));

                ack.put("ack", ackcontent);

                out.println(ack.toString());
            } else if(request.getParameter("action").equals("sendroomchat")) {
                cd.addRoomMessage(request.getParameter("sender"), request.getParameter("room"), request.getParameter("message"));
            } else if(request.getParameter("action").equals("poll")) {
                int n = 0;
                int j = 0;
                boolean found = false;

                ArrayList<chatRoom> cr = (ArrayList<chatRoom>) session.getAttribute("ichat.roomdata");

                JSONArray chatmessages = new JSONArray();
                while(n < cd.message.size()) {
                    if(cd.message.get(n).receiver.equals(session.getAttribute("ichat.username"))) {
                        JSONObject message = new JSONObject();
                        message.put("sender", cd.message.get(n).sender);
                        message.put("receiver", cd.message.get(n).receiver);
                        message.put("room", cd.message.get(n).room);
                        message.put("message", cd.message.get(n).message);
                        chatmessages.put(message);
                        cd.message.remove(n);
                    } else {
                        n++;
                    }
                }
                responseJSON.put("chatmessages", chatmessages);

                n = 0;
                JSONArray roommessages = new JSONArray();
                while(n < cd.roommessage.size()) {
                    // untuk setiap pesan di roommessage
                    found = false;
                    j = 0;
                    // periksa apakah pesan itu untuk dia
                    while(!found && j < cr.size()) {
                        if(cd.roommessage.get(n).room.equals(cr.get(j).name) && n > Integer.parseInt(session.getAttribute("ichat.room.lastMsgID." + cr.get(j).name).toString(), 10)) {
                            found = true;
                        } else {
                            j++;
                        }
                    }
                    
                    // kalau iya
                    if(found) {
                        JSONObject message = new JSONObject();
                        message.put("sender", cd.roommessage.get(n).sender);
                        message.put("room", cd.roommessage.get(n).room);
                        message.put("message", cd.roommessage.get(n).message);
                        roommessages.put(message);
                        session.setAttribute("ichat.room.lastMsgID." + cd.roommessage.get(n).room, n);
                    }

                    n++;
                }
                responseJSON.put("roommessages", roommessages);

                n = 0;
                JSONArray roomusers = new JSONArray();
                while(n < cd.presence.size()) {
                    if(!cd.presence.get(n).username.equals(session.getAttribute("ichat.username").toString())) {
                        JSONObject roomuser = new JSONObject();
                        roomuser.put("username", cd.presence.get(n).username);
                        roomuser.put("room", cd.presence.get(n).room);
                        roomusers.put(roomuser);
                    }

                    n++;
                }
                responseJSON.put("roomusers", roomusers);

                out.println(responseJSON.toString());
            }

            rs.close();
            st.close();
            con.close();
        } catch(SQLException ex) {
            while (ex != null) {
                out.println ("SQL Exception:  " + ex.getMessage ());
                ex = ex.getNextException ();
            }
        } catch(Exception ex) {
            if(ex != null) {
                out.println ("Exception:  " + ex.getMessage ());
            }
        }
    } 

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    } 

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}
